//////////////////////////////////////////////
// TestUtils.h
// 
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Includes ---------------------------------

// nkDebug
#include "../Dll/DllDefines.h"

// nkMemory
#include <NilkinsMemory/Containers/StringView.h>

// Standards
#include <algorithm>
#include <type_traits>

/// Class ------------------------------------

namespace nkDebug
{
	class DLL_NKDEBUG_EXPORT TestUtils final
	{
		public :

			// Testing utilities
			static void check (bool condition, nkMemory::StringView message = "") ;

		public :

			// Template utilities
			template <typename T>
			static void areEqual (const T& a, const T& b, nkMemory::StringView message = "")
			{
				check(a == b, message) ;
			}

			template <typename T>
			static
			std::enable_if_t<!std::is_pointer_v<T>, void>
			areEqual (T a, T b, T precision, nkMemory::StringView message = "")
			{
				check(std::abs(a - b) <= precision, message) ;
			}

			template <typename T>
			static void areNotEqual (const T& a, const T& b, nkMemory::StringView message = "")
			{
				check(a != b, message) ;
			}

			template <typename T>
			static
			std::enable_if_t<!std::is_pointer_v<T>, void>
			areNotEqual (T a, T b, T precision, nkMemory::StringView message = "")
			{
				check(std::abs(a - b) > precision, message) ;
			}

			template <typename T>
			static void isNull (T* p, nkMemory::StringView message = "")
			{
				check(!p, message) ;
			}

			template <typename T>
			static void isNotNull (T* p, nkMemory::StringView message = "")
			{
				check(p, message) ;
			}

		public :

			// Specialized templates
			template <typename T = char*>
			static void areEqual (char* a, char* b, nkMemory::StringView message = "")
			{
				check(nkMemory::StringView(a) == nkMemory::StringView(b), message) ;
			}

			template <typename T = const char*>
			static void areEqual (const char* const& a, const char* const& b, nkMemory::StringView message = "")
			{
				check(nkMemory::StringView(a) == nkMemory::StringView(b), message) ;
			}

			template <typename T = char*>
			static void areNotEqual (char* a, char* b, nkMemory::StringView message = "")
			{
				check(nkMemory::StringView(a) != nkMemory::StringView(b), message) ;
			}

			template <typename T = const char*>
			static void areNotEqual (const char* const& a, const char* const& b, nkMemory::StringView message = "")
			{
				check(nkMemory::StringView(a) != nkMemory::StringView(b), message) ;
			}

		public :

			// Erased specializations
			template <typename T = const char*>
			static void areEqual (const char* a, const char* b, const char* precision, nkMemory::StringView message) = delete ;
	} ;
}